/**
 * @author Mustafa K. Isik
 * requires compilertoys.jar
 */

import toys.base.LexicalError;
import toys.base.PreProcessor;
import toys.base.Source;

public class CommentRemover implements PreProcessor {

	private Source outputSource;

	private static final int PLAIN = 0;
	private static final int INTO = 1;
	private static final int SINGLE_LINE_COMMENT = 2;
	private static final int BLOCK_COMMENT = 3;
	private static final int OUT_OF = 4;

	private int state;

	//code just replaces whitespaces and preserves line feeds
	public Source process(Source inputSource) throws LexicalError {

		char nextElement;
		state = PLAIN;
		outputSource = new Source();

		while(inputSource.more()){
			nextElement = inputSource.get();
			switch(state){
			case PLAIN:	processPlainState(nextElement);	break;
			case INTO:	processIntoState(nextElement); break;
			case SINGLE_LINE_COMMENT: processSingleLineCommentState(nextElement); break;
			case BLOCK_COMMENT:	processBlockCommentState(nextElement); break;
			case OUT_OF: processOutOfState(nextElement); break;
			default: System.out.println("undefined state"); break;
			}
		}
		return outputSource;
	}

	private void processPlainState(char element){
		if(element == '/'){
			state = INTO;
		}else{
			outputSource.put(element);
		}
	}

	private void processIntoState(char element){
		if(element == '/'){
			state = SINGLE_LINE_COMMENT;
		}else if(element == '*'){
			state = BLOCK_COMMENT;
		}else{
			state = PLAIN;
			outputSource.put('/');
		}
	}

	private void processSingleLineCommentState(char element){
		if(element == '\n'){	//TODO:framework "compilertoys" does not seem to provide platform line.separators
			state = PLAIN;
			outputSource.put(System.getProperty("line.separator"));
		}//don't process any characters in the else case
	}

	private void processBlockCommentState(char element){
		if(element == '\n'){	//TODO:framework "compilertoys" does not seem to provide platform line.separators
			outputSource.put(System.getProperty("line.separator"));
		}else if(element == '*'){
			state = OUT_OF;
		}
	}

	private void processOutOfState(char element){
		if(element == '/'){
			state = PLAIN;
			outputSource.put(' ');
		}else if(element != '*'){
			state = BLOCK_COMMENT;
		}
	}
}

